package com.partvoyage.client.mvp2.view.carte;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.Maps;
import com.google.gwt.maps.client.event.MapClickHandler;
import com.google.gwt.maps.client.event.MapRightClickHandler;
import com.google.gwt.maps.client.event.MapZoomEndHandler;
import com.google.gwt.maps.client.event.MarkerDragEndHandler;
import com.google.gwt.maps.client.geocode.Geocoder;
import com.google.gwt.maps.client.geocode.LocationCallback;
import com.google.gwt.maps.client.geocode.Placemark;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.Size;
import com.google.gwt.maps.client.overlay.Icon;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.partvoyage.client.mvp2.event.CarteZoomEvent;
import com.partvoyage.client.mvp2.event.ChargerPhotoFacebookEvent;
import com.partvoyage.client.mvp2.event.ChargerPointEvent;
import com.partvoyage.client.mvp2.event.ChargerPointWikipediaEvent;
import com.partvoyage.client.mvp2.event.ChargerPhotoPicassaEvent;
import com.partvoyage.client.mvp2.event.CreerPointEvent;
import com.partvoyage.client.mvp2.event.LoadDataCarteEvent;
import com.partvoyage.client.mvp2.event.LoadDataDetailPointEvent;
import com.partvoyage.client.mvp2.event.LoadDataDetailPointEvent.TYPE_DETAIL_POINT;
import com.partvoyage.client.mvp2.event.LoadDataInformationPointEvent;
import com.partvoyage.client.mvp2.event.LoadDataInformationPointEvent.TYPE_INFORMATION_POINT;
import com.partvoyage.client.mvp2.event.SupprimerPointCourantEvent;
import com.partvoyage.client.mvp2.event.SupprimerTousLesPointsEvent;
import com.partvoyage.client.mvp2.framework.MVPDisplay;
import com.partvoyage.client.mvp2.framework.MVPPresenter;
import com.partvoyage.client.mvp2.view.carte.service.CartePresentationService;
import com.partvoyage.client.outil.PhotoPicassaSurLaCarte;
import com.partvoyage.client.outil.PointSurLaCarte;
import com.partvoyage.client.outil.PointWikiPediaSurLaCarte;
import com.partvoyage.client.service.calendrier.CalendarService;
import com.partvoyage.client.service.calendrier.CalendarServiceAsync;
import com.partvoyage.client.service.infopoint.InfoPointService;
import com.partvoyage.client.service.infopoint.InfoPointServiceAsync;
import com.partvoyage.client.service.picassa.PicassaService;
import com.partvoyage.client.service.picassa.PicassaServiceAsync;
import com.partvoyage.client.service.projet.ProjetBean;
import com.partvoyage.client.service.wikipedia.WikipediaService;
import com.partvoyage.client.service.wikipedia.WikipediaServiceAsync;
import com.partvoyage.client.sessionClient.SessionClient;
import com.partvoyage.shared.Constants;
import com.partvoyage.shared.GeonameWikiPediaBean;
import com.partvoyage.shared.InfoPointBean;
import com.partvoyage.shared.InfoPointBean.TYPE_ZOOM_LEVEL;
import com.partvoyage.shared.PhotoBean;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.layout.HLayout;

public class CartePresenter extends MVPPresenter<CartePresenter.Display> {
	protected final InfoPointServiceAsync infoService = GWT
			.create(InfoPointService.class);
	private final CalendarServiceAsync calendarService = GWT
			.create(CalendarService.class);
	private List<PointWikiPediaSurLaCarte> pointWikiPediaSurLaCartes = new ArrayList<PointWikiPediaSurLaCarte>();
	private List<PhotoPicassaSurLaCarte> photoPicassaSurLaCartes = new ArrayList<PhotoPicassaSurLaCarte>();
	protected final PicassaServiceAsync picassaService = GWT
			.create(PicassaService.class);
	protected final WikipediaServiceAsync wikipediaService = GWT
			.create(WikipediaService.class);
	private Integer ZOOM_PAR_DEFAUT = 14;

	// private GestionDirection gestionDirection;

	public interface Display extends MVPDisplay {
		MapWidget getMap();

		void supprimerPointCarte();

		void chargerCarte(HLayout container);

		void nettoyerLaCarte();

	}

	public CartePresenter(final Display display, final HandlerManager eventBus) {
		super(display, eventBus);
		// initialise();
	}

	// private void initialise() {
	// gestionDirection = new GestionDirection();
	//
	// }

	protected void registerHandler() {
		eventBus.addHandler(CreerPointEvent.TYPE,
				new CreerPointEvent.CreerPointEventHandler() {

					@Override
					public void onCreerPoint(final CreerPointEvent event) {
						// TODO le service infoService.getPlaceName ne
						// fonctionne pas, à tester
						// infoService.getPlaceName
						// TODO trouver uin moyen avec geocoder pour avoir le
						// nom de la ville si le zoom est moyen, pays si
						// grand...
						// voir
						// http://code.google.com/p/gwt-google-apis/source/browse/trunk/samples/maps/src/com/google/gwt/maps/sample/?r=159#sample%2Fmaps%2Fclient%253Fstate%253Dclosed
						// TODO voir geocache pour cacher les résultats
						final Geocoder geocoder = new Geocoder();
						geocoder.getLocations(
								LatLng.newInstance(event.getLatitude(),
										event.getLongitude()),
								new LocationCallback() {

									@Override
									public void onSuccess(
											JsArray<Placemark> locations) {
										Placemark place = locations.get(0);
										String ou = getOu(place);
										String codePays = place.getCountry();
										creerPoint(event, ou, codePays);

									}

									private void creerPoint(
											final CreerPointEvent event) {
										creerPoint(event, null, null);
									}

									private void creerPoint(
											final CreerPointEvent event,
											String ou, String codePays) {
										infoService.create(
												SessionClient.getInstance()
														.getProjetBeanCourant()
														.getProjetId(),
												event.getLatitude(),
												event.getLongitude(),
												"",
												"",
												"",
												"",
												null,
												ou,
												codePays,
												getZoomCourant(),
												null,
												new AsyncCallback<InfoPointBean>() {
													public void onFailure(
															Throwable caught) {
														Window.alert("erreur lors de la création du point du projet "
																+ SessionClient
																		.getInstance()
																		.getProjetBeanCourant()
																		.getProjetId());
													}

													@SuppressWarnings("deprecation")
													public void onSuccess(
															InfoPointBean infoPointBean) {
														PointSurLaCarte pointSurLaCarte = new PointSurLaCarte(
																infoPointBean,
																Boolean.TRUE);
														// gestion du glisser
														// /deplacer
														// pointSurLaCarte
														// .addMarkerDragStartHandler(new
														// PointSurLaCarteGlisserDeplacerStartHandler());
														pointSurLaCarte
																.addMarkerDragEndHandler(new PointSurLaCarteGlisserDeplacerEndHandler());
														InfoPointBean infoPointBeanCourant = SessionClient
																.getInstance()
																.getInfoPointBeanCourant();
														if (infoPointBeanCourant != null) {
															retirerFocusSurPoint(infoPointBeanCourant);
														}
														ajouterPointEtAfficherDansLaCarte(pointSurLaCarte);
														SessionClient
																.getInstance()
																.setInfoPointBeanCourant(
																		infoPointBean);
														// clean information
														// point
														eventBus.fireEvent(new LoadDataInformationPointEvent(
																infoPointBean,
																TYPE_INFORMATION_POINT.TYPE_ALL));
														eventBus.fireEvent(new LoadDataDetailPointEvent(
																infoPointBean,
																TYPE_DETAIL_POINT.TYPE_REALOAD_OU));
														if (SessionClient
																.getInstance()
																.estWikipediaActive()) {
															// ajout des points
															// wikipedia
															eventBus.fireEvent(new ChargerPointWikipediaEvent(
																	infoPointBean
																			.getLatitude(),
																	infoPointBean
																			.getLongitude()));
														}
														if (SessionClient
																.getInstance()
																.estPhotoPicassaActive()) {
															// ajout des points
															// wikipedia
															eventBus.fireEvent(new ChargerPhotoPicassaEvent(
																	infoPointBean
																			.getLatitude(),
																	infoPointBean
																			.getLongitude()));

														}
														// ajout des points
														// wikipedia
														eventBus.fireEvent(new ChargerPhotoFacebookEvent(
																infoPointBean
																		.getOu(),
																infoPointBean
																		.getLatitude()
																		+ (Math.random() * 0),
																infoPointBean
																		.getLongitude()
																		+ (Math.random() * 0)));
													}
												});
									}

									@Override
									public void onFailure(int statusCode) {
										creerPoint(event);

									}
								});

						// GeocoderRequest geocoderRequest = new
						// GeocoderRequestBuilder().setAddress("Rijnsburgstraat 9-11, Amsterdam, The Netherlands").getGeocoderRequest();
						// GeocodeResponse geocoderResponse =
						// geocoder.geocode(geocoderRequest);
						// List<GeocoderResult> results =
						// geocoderResponse.getResults();
						// float latitude =
						// results.get(0).getGeometry().getLocation().getLat().floatValue();
						// float longitude =
						// results.get(0).getGeometry().getLocation().getLng().floatValue();
						// assertEquals(52.347797f, latitude);
						// assertEquals(4.8507648f, longitude);

					}
				});
		// affichage de la reponse
		eventBus.addHandler(LoadDataCarteEvent.TYPE,
				new LoadDataCarteEvent.LoadDataCarteEventHandler() {

					@Override
					public void onLoadDataCarte(LoadDataCarteEvent event) {
						infoService.findAllByProjetId(SessionClient
								.getInstance().getProjetBeanCourant()
								.getProjetId(),
								new AsyncCallback<List<InfoPointBean>>() {
									public void onFailure(Throwable caught) {
										Window.alert("erreur lors de la récupération des points du projet "
												+ SessionClient.getInstance()
														.getProjetBeanCourant()
														.getProjetId());
									}

									@Override
									public void onSuccess(
											List<InfoPointBean> infoPointBeans) {
										setMapAuCentre();
										display.nettoyerLaCarte();
										SessionClient.getInstance()
												.resetPointSurLaCarte();
										// ajouter les points
										for (InfoPointBean infoPointBean : infoPointBeans) {
											PointSurLaCarte pointSurLaCarte = new PointSurLaCarte(
													infoPointBean,
													Boolean.FALSE);
											pointSurLaCarte
													.addMarkerDragEndHandler(new PointSurLaCarteGlisserDeplacerEndHandler());
											ajouterPointEtAfficherDansLaCarte(pointSurLaCarte);
										}
										// ajouter les directions
										for (InfoPointBean infoPointBean : infoPointBeans) {
											if (infoPointBean
													.getMarkerIdDestination() == null) {
												continue;
											}
											PointSurLaCarte pointSurLaCarteSource = CartePresentationService
													.getPointSurLaCarteFromListe(infoPointBean);
											PointSurLaCarte pointSurLaCarteDestination = CartePresentationService
													.getPointSurLaCarteFromListe(CartePresentationService
															.getInfoPointBeanDestinationFromListe(
																	infoPointBeans,
																	infoPointBean));
											CartePresentationService.creerRoute(
													display.getMap(),
													pointSurLaCarteSource,
													pointSurLaCarteDestination);
										}
										// gestion du zoom
										gestionZoom(getZoomCourant());
									}

								});

					}

				});

		eventBus.addHandler(CarteZoomEvent.TYPE,
				new CarteZoomEvent.CarteZoomEventHandler() {

					@Override
					public void onZoom(CarteZoomEvent event) {
						setMapALAdresseEtZoom(event.getAdresse(),
								event.getZoomLevel());
					}

				});

		eventBus.addHandler(
				ChargerPointWikipediaEvent.TYPE,
				new ChargerPointWikipediaEvent.ChargerPointWikipediaEventHandler() {

					@Override
					public void onChargerPointWikipedia(
							ChargerPointWikipediaEvent event) {
						wikipediaService.getGeonameWikiPediaBean(
								event.getLatitude(),
								event.getLongitude(),
								new AsyncCallback<List<GeonameWikiPediaBean>>() {

									@Override
									public void onSuccess(
											List<GeonameWikiPediaBean> result) {
										for (final GeonameWikiPediaBean geonameWikiPediaBean : result) {
											PointWikiPediaSurLaCarte pointWikiPediaSurLaCarte = new PointWikiPediaSurLaCarte(
													geonameWikiPediaBean);
											afficherPointWikiPedia(pointWikiPediaSurLaCarte);
										}

									}

									@Override
									public void onFailure(Throwable caught) {
										System.out.println(caught);

									}
								});
					}
				});

		eventBus.addHandler(ChargerPhotoPicassaEvent.TYPE,
				new ChargerPhotoPicassaEvent.ChargerPhotoPicassaEventHandler() {

					@Override
					public void onChargerPhotoPicassa(
							ChargerPhotoPicassaEvent event) {
						picassaService.listPhoto("Paris",
								new AsyncCallback<List<PhotoBean>>() {

									@Override
									public void onFailure(Throwable caught) {
										// TODO Auto-generated method stub

									}

									@Override
									public void onSuccess(List<PhotoBean> result) {
										for (final PhotoBean photo : result) {
											Icon icon = Icon.newInstance(photo
													.getPhotoUrl());
											// icon.setIconSize(Size.newInstance(
											// 20, 34));
											MarkerOptions ops = MarkerOptions
													.newInstance(icon);
											PhotoPicassaSurLaCarte photoPicassaSurLaCarte = new PhotoPicassaSurLaCarte(
													photo);
											afficherPhotoPicassa(photoPicassaSurLaCarte);
										}

									}

								});
					}
				});
		eventBus.addHandler(
				ChargerPhotoFacebookEvent.TYPE,
				new ChargerPhotoFacebookEvent.ChargerPhotoFacebookEventHandler() {

					@Override
					public void onChargerPhotoFacebook(
							final ChargerPhotoFacebookEvent event) {
						infoService.getImgFromFriends(event.getUrl(),
								new AsyncCallback<List<String>>() {

									@Override
									public void onFailure(Throwable caught) {
										// TODO Auto-generated method stub

									}

									@Override
									public void onSuccess(List<String> result) {
										for (final String url : result) {
											PhotoBean photo = new PhotoBean();
											double la = (Math.round(Math.random())>0.5?1:-1)
											* (Math.random() * 0.05);
											double lo = (Math.round(Math.random())>0.5?1:-1)
											* (Math.random() * 0.05);
											photo.setLatitude(event
													.getLatitude()
													+ la);
											photo.setLongitude(event
													.getLongitude()
													+ lo);
											photo.setPhotoUrl(url);
											Icon icon = Icon.newInstance(url);
											// icon.setIconSize(Size.newInstance(
											// 20, 34));
											MarkerOptions ops = MarkerOptions
													.newInstance(icon);
											PhotoPicassaSurLaCarte photoPicassaSurLaCarte = new PhotoPicassaSurLaCarte(
													photo, ops);

											afficherPhotoPicassa(photoPicassaSurLaCarte);
										}
									}

								});
					}
				});
		eventBus.addHandler(ChargerPointEvent.TYPE,
				new ChargerPointEvent.ChargerPointEventHandler() {

					@Override
					public void onChargerPoint(final ChargerPointEvent event) {
						// récupération des informations du marker
						infoService.findById(event.getInfoPointBean()
								.getMarkerId(),
								new AsyncCallback<InfoPointBean>() {
									public void onFailure(Throwable caught) {
										Window.alert("erreur lors de la récupération du point du projet "
												+ SessionClient.getInstance()
														.getProjetBeanCourant()
														.getProjetId());
									}

									@Override
									public void onSuccess(
											InfoPointBean infoPointBean) {
										gestionDuFocus(infoPointBean);
										SessionClient.getInstance()
												.setInfoPointBeanCourant(
														infoPointBean);
										eventBus.fireEvent(new LoadDataInformationPointEvent(
												infoPointBean,
												TYPE_INFORMATION_POINT.TYPE_ALL));
										eventBus.fireEvent(new LoadDataDetailPointEvent(
												infoPointBean,
												TYPE_DETAIL_POINT.TYPE_REALOAD_OU));
										if (SessionClient.getInstance()
												.estWikipediaActive()) {
											// ajout des points
											// wikipedia
											eventBus.fireEvent(new ChargerPointWikipediaEvent(
													infoPointBean.getLatitude(),
													infoPointBean
															.getLongitude()));
										}
									}

								});

					}
				});
		eventBus.addHandler(
				SupprimerPointCourantEvent.TYPE,
				new SupprimerPointCourantEvent.SupprimerPointCourantEventHandler() {

					@Override
					public void onSupprimerPointCourant(
							SupprimerPointCourantEvent event) {
						final InfoPointBean infoPointBeanCourant = SessionClient
								.getInstance().getInfoPointBeanCourant();
						infoService.supprimerPoint(
								infoPointBeanCourant.getMarkerId(),
								new AsyncCallback<Void>() {

									@Override
									public void onSuccess(Void result) {
										retirerPointDeCarte(recherchePointDansCarte(infoPointBeanCourant));
									}

									@Override
									public void onFailure(Throwable caught) {
										// TODO Auto-generated method stub

									}
								});

					}
				});
		eventBus.addHandler(
				SupprimerTousLesPointsEvent.TYPE,
				new SupprimerTousLesPointsEvent.SupprimerTousLesPointsEventHandler() {

					@Override
					public void onSupprimerTousLesPoints(
							SupprimerTousLesPointsEvent event) {
						ProjetBean projetBeanCourant = SessionClient
								.getInstance().getProjetBeanCourant();
						infoService.deleteAllByProjetId(
								projetBeanCourant.getProjetId(),
								new AsyncCallback<Void>() {
									@Override
									public void onSuccess(Void result) {
										List<InfoPointBean> infoPointBeans = new ArrayList<InfoPointBean>();
										for (PointSurLaCarte pointSurLaCarte : SessionClient
												.getInstance()
												.getPointSurLaCartes()) {
											infoPointBeans.add(pointSurLaCarte
													.getInfo());
										}
										for (final InfoPointBean infoPointBean : infoPointBeans) {
											retirerPointDeCarte(recherchePointDansCarte(infoPointBean));
										}
										// nettoyage des routes
										CartePresentationService
												.nettoyageRoutes();

									}

									@Override
									public void onFailure(Throwable caught) {
										// TODO Auto-generated method stub

									}
								});

					}
				});
	}

	private void setMapAuCentre() {
		LatLng bergame = LatLng.newInstance(45.6949028, 9.6699528);
		display.getMap().setCenter(bergame);
		display.getMap().setZoomLevel(ZOOM_PAR_DEFAUT);
	}

	private void setMapALAdresseEtZoom(String adresse, final int zoomLevel) {
		// attention geocoder ne peut etre défini en variable de classe
		final Geocoder geocoder = new Geocoder();
		geocoder.getLocations(adresse, new LocationCallback() {

			@Override
			public void onSuccess(JsArray<Placemark> locations) {
				Placemark place = locations.get(0);
				display.getMap().setCenter(place.getPoint());
				display.getMap().setZoomLevel(zoomLevel);
				gestionZoom(zoomLevel);
			}

			@Override
			public void onFailure(int statusCode) {
				// TODO Auto-generated method stub

			}

		});

	}

	private int getZoomCourant() {
		return display.getMap().getZoomLevel();
	}

	private String getOu(Placemark place) {
		int zoomlevel = getZoomCourant();
		TYPE_ZOOM_LEVEL zoomLevel = CartePresentationService
				.getZoomLevel(zoomlevel);
		String ou;
		if (zoomLevel.equals(TYPE_ZOOM_LEVEL.PAYS_LEVEL)) {
			ou = place.getCountry();
		} else if (zoomLevel.equals(TYPE_ZOOM_LEVEL.VILLE_LEVEL)) {
			ou = place.getCity();
		} else {
			ou = place.getAddress();
		}
		return ou;
	}

	private void gestionDuFocus(InfoPointBean infoPointBean) {
		InfoPointBean infoPointBeanCourant = SessionClient.getInstance()
				.getInfoPointBeanCourant();
		if (infoPointBeanCourant != null
				&& !infoPointBean.getMarkerId().equals(
						infoPointBeanCourant.getMarkerId())) {
			retirerFocusSurPoint(infoPointBeanCourant);
			ajouterFocusSurPoint(infoPointBean);
		}

	}

	private void retirerFocusSurPoint(InfoPointBean infoPointBean) {
		PointSurLaCarte ancienPointAvecFocus = recherchePointDansCarte(infoPointBean);
		if (ancienPointAvecFocus != null) {
			retirerPointDeCarte(ancienPointAvecFocus);
			ancienPointAvecFocus = new PointSurLaCarte(
					ancienPointAvecFocus.getInfo(), Boolean.FALSE);
			ancienPointAvecFocus
					.addMarkerDragEndHandler(new PointSurLaCarteGlisserDeplacerEndHandler());
			ajouterPointEtAfficherDansLaCarte(ancienPointAvecFocus);
		}
	}

	private void ajouterFocusSurPoint(InfoPointBean infoPointBeanCourant) {
		PointSurLaCarte ancienPointSansFocus = recherchePointDansCarte(infoPointBeanCourant);
		if (ancienPointSansFocus != null) {
			retirerPointDeCarte(ancienPointSansFocus);
			ancienPointSansFocus = new PointSurLaCarte(
					ancienPointSansFocus.getInfo(), Boolean.TRUE);
			ancienPointSansFocus
					.addMarkerDragEndHandler(new PointSurLaCarteGlisserDeplacerEndHandler());
			ajouterPointEtAfficherDansLaCarte(ancienPointSansFocus);
		}
	}

	private void retirerPointDeCarte(PointSurLaCarte pointARetirer) {
		if (pointARetirer == null) {
			return;
		}
		retirerPointDeLaListeDePointSurLaCartes(pointARetirer);
		display.getMap().removeOverlay(pointARetirer);
	}

	private void retirerPointDeLaListeDePointSurLaCartes(
			PointSurLaCarte pointARetirer) {
		List<PointSurLaCarte> listTemp = new ArrayList<PointSurLaCarte>();
		for (PointSurLaCarte pointSurLaCarte : SessionClient.getInstance()
				.getPointSurLaCartes()) {
			if (pointSurLaCarte.getInfo().getMarkerId()
					.equals(pointARetirer.getInfo().getMarkerId())) {
				continue;
			}
			listTemp.add(pointSurLaCarte);
		}
		SessionClient.getInstance().setPointSurLaCartes(listTemp);
	}

	private PointSurLaCarte recherchePointDansCarte(InfoPointBean infoPointBean) {
		PointSurLaCarte pointAChercher = null;
		for (PointSurLaCarte pointSurLaCarte : SessionClient.getInstance()
				.getPointSurLaCartes()) {
			if (pointSurLaCarte.getInfo().getMarkerId()
					.equals(infoPointBean.getMarkerId())) {
				pointAChercher = pointSurLaCarte;
				break;
			}
		}
		return pointAChercher;
	}

	/**
	 * Lie le bouton send à l'action ....
	 */
	protected void bind() {
		display.getMap().addMapClickHandler(new MapClickHandler() {
			public void onClick(MapClickEvent e) {
				if (e.getOverlay() == null) {
					// création d'un point sur la carte
					eventBus.fireEvent(new CreerPointEvent(e.getLatLng()
							.getLatitude(), e.getLatLng().getLongitude()));
					// Marker marker = (Marker)e.getOverlay();
					// marker.set
				} else if (e.getOverlay() instanceof PointSurLaCarte) {
					PointSurLaCarte pointSurLaCarte = (PointSurLaCarte) e
							.getOverlay();
					eventBus.fireEvent(new ChargerPointEvent(pointSurLaCarte
							.getInfo()));

				}
				// le clic gauche annule le clic droit pour créer une route
				SessionClient.getInstance().setSourcePourRoute(null);
			}
		});
		display.getMap().addMapRightClickHandler(new MapRightClickHandler() {

			@Override
			public void onRightClick(MapRightClickEvent e) {
				if (e.getOverlay() == null) {
					// TODO
				} else if (e.getOverlay() instanceof PointSurLaCarte) {
					PointSurLaCarte pointSurLaCarte = (PointSurLaCarte) e
							.getOverlay();
					if (SessionClient.getInstance().isSourcePourRoute()) {
						PointSurLaCarte sourcePourRoute = SessionClient
								.getInstance().getSourcePourRoute();
						CartePresentationService.creerRoute(display.getMap(),
								sourcePourRoute, pointSurLaCarte);
					} else {
						eventBus.fireEvent(new ChargerPointEvent(
								pointSurLaCarte.getInfo()));
						SessionClient.getInstance().setSourcePourRoute(
								pointSurLaCarte);

					}

					// gestionDirection.ajouterPointEtDessiner(pointSurLaCarte);
				}
			}
		});
		display.getMap().addMapZoomEndHandler(new MapZoomEndHandler() {

			@Override
			public void onZoomEnd(MapZoomEndEvent event) {
				System.out.println("Zoom: " + event.getNewZoomLevel());
				gestionZoom(event.getNewZoomLevel());
			}

		});
	}

	private void gestionZoom(int zoomlevel) {
		TYPE_ZOOM_LEVEL zoomLevel = CartePresentationService
				.getZoomLevel(zoomlevel);
		String ou;
		if (zoomLevel.equals(TYPE_ZOOM_LEVEL.PAYS_LEVEL)) {
			// si on est en zoom pays, on efface tous les points
			// quartiers
			nettoyagePointEnFonctionZoom(Boolean.FALSE,
					TYPE_ZOOM_LEVEL.ADRESSE_LEVEL);
			nettoyagePointEnFonctionZoom(Boolean.TRUE,
					TYPE_ZOOM_LEVEL.PAYS_LEVEL, TYPE_ZOOM_LEVEL.VILLE_LEVEL);
		} else if (zoomLevel.equals(TYPE_ZOOM_LEVEL.VILLE_LEVEL)) {
			// si on est en zoom ville , on efface tous les points pays et
			// adresses
			nettoyagePointEnFonctionZoom(Boolean.FALSE,
					TYPE_ZOOM_LEVEL.PAYS_LEVEL, TYPE_ZOOM_LEVEL.ADRESSE_LEVEL);
			nettoyagePointEnFonctionZoom(Boolean.TRUE,
					TYPE_ZOOM_LEVEL.VILLE_LEVEL);
		} else {
			// si on est en zoom quartier, on efface tous les points
			// villes et pays
			nettoyagePointEnFonctionZoom(Boolean.FALSE,
					TYPE_ZOOM_LEVEL.PAYS_LEVEL, TYPE_ZOOM_LEVEL.VILLE_LEVEL);
			nettoyagePointEnFonctionZoom(Boolean.TRUE,
					TYPE_ZOOM_LEVEL.ADRESSE_LEVEL);
		}
	}

	private void nettoyagePointEnFonctionZoom(Boolean afficher,
			TYPE_ZOOM_LEVEL... listeNiveauxDeNettoyage) {
		double latitudeNordEst = display.getMap().getBounds().getNorthEast()
				.getLatitude();
		double longitudeNordEst = display.getMap().getBounds().getNorthEast()
				.getLongitude();
		double latitudeSudWest = display.getMap().getBounds().getSouthWest()
				.getLatitude();
		double longitudeSudWest = display.getMap().getBounds().getSouthWest()
				.getLongitude();

		for (PointSurLaCarte pointSurLaCarte : SessionClient.getInstance()
				.getPointSurLaCartes()) {
			double latitude = pointSurLaCarte.getLatLng().getLatitude();
			double longitude = pointSurLaCarte.getLatLng().getLongitude();
			if (latitudeSudWest <= latitude && latitude <= latitudeNordEst
					&& longitudeSudWest <= longitude
					&& longitude <= longitudeNordEst) {
				TYPE_ZOOM_LEVEL niveauZoomInfoPoint = CartePresentationService
						.getZoomLevel(pointSurLaCarte.getInfo().getZoomLevel());
				for (TYPE_ZOOM_LEVEL niveauZoomANettoyer : listeNiveauxDeNettoyage) {
					if (niveauZoomInfoPoint.equals(niveauZoomANettoyer)) {
						pointSurLaCarte.setVisible(afficher);
					}

				}
			}
		}
	}

	@Override
	public void go(final HasWidgets container) {

	}

	public void go(HLayout container) {

	}

	public void initialiserCarte(final HLayout container) {
		Maps.loadMapsApi(Constants.GOOGLE_MAP_KEY, "2", false, new Runnable() {
			public void run() {
				display.chargerCarte(container);
				bind();
				loadData();
			}
		});
	}

	protected void loadData() {
		eventBus.fireEvent(new LoadDataCarteEvent());

	}

	private void ajouterPointEtAfficherDansLaCarte(
			PointSurLaCarte pointAAjouterEtAfficher) {
		SessionClient.getInstance().addPointSurLaCarte(pointAAjouterEtAfficher);
		afficherPoint(pointAAjouterEtAfficher);
	}

	private void afficherPoint(PointSurLaCarte pointSurLaCarte) {
		display.getMap().addOverlay(pointSurLaCarte);
	}

	private void afficherPointWikiPedia(
			PointWikiPediaSurLaCarte pointWikiPediaSurLaCarte) {
		display.getMap().addOverlay(pointWikiPediaSurLaCarte);
		pointWikiPediaSurLaCartes.add(pointWikiPediaSurLaCarte);

	}

	private void afficherPhotoPicassa(
			PhotoPicassaSurLaCarte photoPicassaSurLaCarte) {
		display.getMap().addOverlay(photoPicassaSurLaCarte);
		photoPicassaSurLaCartes.add(photoPicassaSurLaCarte);

	}

	private class PointSurLaCarteGlisserDeplacerEndHandler implements
			MarkerDragEndHandler {

		@Override
		public void onDragEnd(final MarkerDragEndEvent event) {

			final LatLng latLng = event.getSender().getLatLng();
			final PointSurLaCarte pointSurLaCarte = (PointSurLaCarte) event
					.getSender();
			InfoPointBean infoPointBeanCourant = SessionClient.getInstance()
					.getInfoPointBeanCourant();
			final InfoPointBean infoPointBean = pointSurLaCarte.getInfo();
			if (infoPointBeanCourant != null
					&& infoPointBean != null
					&& !infoPointBean.getMarkerId().equals(
							infoPointBeanCourant.getMarkerId())) {
				chargerUnAutrePoint(latLng, infoPointBean);
			} else {
				chargerPointCourant(latLng, infoPointBean);
			}
		}

		private void chargerPointCourant(final LatLng latLng,
				final InfoPointBean infoPointBeanCourant) {
			// attention geocoder ne peut etre défini en variable de classe
			final Geocoder geocoder = new Geocoder();
			geocoder.getLocations(
					LatLng.newInstance(latLng.getLatitude(),
							latLng.getLongitude()), new LocationCallback() {

						@Override
						public void onSuccess(JsArray<Placemark> locations) {
							Placemark place = locations.get(0);
							String ou = getOu(place);
							String codePays = place.getCountry();
							updateLocation(ou, codePays);

						}

						private void updateLocation(String ou, String codePays) {
							infoPointBeanCourant.setLatitude(latLng
									.getLatitude());
							infoPointBeanCourant.setLongitude(latLng
									.getLongitude());
							infoPointBeanCourant.setOu(ou);
							infoPointBeanCourant.setCodePays(codePays);
							infoService.update(infoPointBeanCourant,
									new AsyncCallback<InfoPointBean>() {

										@Override
										public void onSuccess(
												InfoPointBean result) {
											SessionClient.getInstance()
													.setInfoPointBeanCourant(
															result);
											eventBus.fireEvent(new LoadDataDetailPointEvent(
													result,
													TYPE_DETAIL_POINT.TYPE_REALOAD_OU));

										}

										@Override
										public void onFailure(Throwable caught) {
											SC.logWarn("Error " + caught);
										}
									});
						}

						@Override
						public void onFailure(int statusCode) {
							// TODO Auto-generated method stub

						}

					});
		}

		private void chargerUnAutrePoint(final LatLng latLng,
				final InfoPointBean infoPointBean) {
			final Geocoder geocoder = new Geocoder();
			geocoder.getLocations(
					LatLng.newInstance(latLng.getLatitude(),
							latLng.getLongitude()), new LocationCallback() {

						@Override
						public void onSuccess(JsArray<Placemark> locations) {
							Placemark place = locations.get(0);
							String ou = getOu(place);
							String codePays = place.getCountry();
							updatePoint(infoPointBean, ou, codePays);

						}

						private void updatePoint(
								final InfoPointBean infoPointBean, String ou,
								String codePays) {
							infoPointBean.setLatitude(latLng.getLatitude());
							infoPointBean.setLongitude(latLng.getLongitude());
							infoPointBean.setOu(ou);
							infoPointBean.setCodePays(codePays);
							infoService.update(infoPointBean,
									new AsyncCallback<InfoPointBean>() {

										@Override
										public void onSuccess(
												InfoPointBean infoPointBeanMiseAjour) {

											gestionDuFocus(infoPointBeanMiseAjour);
											SessionClient
													.getInstance()
													.setInfoPointBeanCourant(
															infoPointBeanMiseAjour);
											eventBus.fireEvent(new LoadDataInformationPointEvent(
													infoPointBeanMiseAjour,
													TYPE_INFORMATION_POINT.TYPE_ALL));
											eventBus.fireEvent(new LoadDataDetailPointEvent(
													infoPointBeanMiseAjour,
													TYPE_DETAIL_POINT.TYPE_REALOAD_OU));
											if (SessionClient.getInstance()
													.estWikipediaActive()) {
												// ajout des points
												// wikipedia
												eventBus.fireEvent(new ChargerPointWikipediaEvent(
														infoPointBeanMiseAjour
																.getLatitude(),
														infoPointBeanMiseAjour
																.getLongitude()));
											}

										}

										@Override
										public void onFailure(Throwable caught) {
											SC.logWarn("Error " + caught);
										}
									});
						}

						@Override
						public void onFailure(int statusCode) {
							// TODO Auto-generated method stub

						}

					});
		}
	}

}
